package com.tanhua.server.service;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.PageUtil;
import cn.hutool.db.PageResult;
import com.github.tobato.fastdfs.domain.conn.FdfsWebServer;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.tanhua.autoconfig.template.OssTemplate;
import com.tanhua.dubbo.api.UserInfoApi;
import com.tanhua.dubbo.api.VideoApi;
import com.tanhua.model.domain.UserInfo;
import com.tanhua.model.domain.Video;
import com.tanhua.model.vo.PageResultVo;
import com.tanhua.model.vo.VideoVo;
import com.tanhua.server.exception.BusinessException;
import com.tanhua.server.exception.ErrorResult;
import com.tanhua.server.interceptor.UserHolderThreadLocal;
import com.tanhua.utils.Constants;
import jdk.nashorn.internal.runtime.regexp.joni.ast.StringNode;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Description: test
 * @Create by: JJ菜菜
 * @Date: 2021/12/7 22:32
 */
@Service
public class SmallVideosService {

    @Autowired
    private FastFileStorageClient client;

    @Autowired
    private FdfsWebServer webServer;

    @Autowired
    private OssTemplate ossTemplate;

    @DubboReference
    private VideoApi videoApi;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @DubboReference
    private UserInfoApi userInfoApi;

    /**
     * 发布小视频
     * @param videoThumbnail
     * @param videoFile
     */
    // 发布视频清空缓存
    @CacheEvict(value = "videos", allEntries = true)
    public void saveVideos(MultipartFile videoThumbnail, MultipartFile videoFile) throws IOException {

        if (videoThumbnail.isEmpty() || videoFile.isEmpty()){
            throw new BusinessException(ErrorResult.error());
        }

        // 1. 将视频视频上传到FastDFS上，获取访问url
        String filename = videoFile.getOriginalFilename();
        String substring = filename.substring(filename.lastIndexOf(".") + 1);
        StorePath storePath = client.uploadFile(videoFile.getInputStream(), videoFile.getSize(), substring, null);
        String videoUrl =  webServer.getWebServerUrl() + storePath.getFullPath();
        // 2. 将封面图片上传到阿里云OSS，获取访问的url
        String imageUrl = ossTemplate.upload(videoThumbnail.getOriginalFilename(), videoThumbnail.getInputStream());
        // 3. 构建videos对象
        Video video = new Video();
        video.setUserId(UserHolderThreadLocal.getId());
        video.setPicUrl(imageUrl);
        video.setVideoUrl(videoUrl);
        video.setText("我就是我，不一样的烟花");
        // 4. 调用api保存数据
        String videoId = videoApi.save(video);
        if (StringUtils.isEmpty(videoId)) {
            throw new BusinessException(ErrorResult.error());
        }
    }

    /**
     * 视频列表
     * @param page
     * @param pagesize
     * @return
     */
    // 分页列表存入缓存  userId_page_pageSize  ,查询是否有缓存，如果有使用缓存，如果没有就执行方法
    @Cacheable(
            value = "videos",
            key = "T(com.tanhua.server.interceptor.UserHolderThreadLocal).getId()+'_'+#page+'_'+#pagesize"
    )
    public PageResultVo queryVideoList(Integer page, Integer pagesize) {

        // 1. 查询redis数据
        String redisKey = Constants.VIDEOS_RECOMMEND +UserHolderThreadLocal.getId();
        String redisValue = redisTemplate.opsForValue().get(redisKey);
        // 2. 判断redis数据是否存在， 判断redis中的数据是否满足本次分页条数
        List<Video> list = new ArrayList<>();
        int redisPages = 0;
        if(!StringUtils.isEmpty(redisValue)) {
            // 3. 如果redis数据存在，根据vid查询数据
            String[] values = redisValue.split(",");
            // 4. 判断当前页的起始条数是否小于数组总数
            if((page - 1) * pagesize < values.length){
                // 使用stream流进行分页查询
                List<Long> vids = Arrays.stream(values)
                        .skip((page - 1) * pagesize)
                        .limit(pagesize)
                        .map(e -> Long.valueOf(e))
                        .collect(Collectors.toList());
                //5、调用API根据PID数组查询动态数据
                list = videoApi.findMovementsByVids(vids);
            }
            redisPages = PageUtil.totalPage(values.length, pagesize);
        }

        // 如果redis数据不存在分页查询视频数据
        if (list.isEmpty()) {
            // page的计算规则， page - redis查询的总页数
            list = videoApi.queryVideoList(page - redisPages, pagesize);
        }

        // 提取视频列表中的用户id
        List<Long> userIds = CollectionUtil.getFieldValues(list, "userId", Long.class);
        // 查询用户信息
        Map<Long, UserInfo> map = userInfoApi.findByIds(null, userIds);
        List<VideoVo> vos = new ArrayList<>();
        for (Video video : list) {
            UserInfo userInfo = map.get(video.getUserId());
            if (userInfo != null){
                VideoVo vo = VideoVo.init(userInfo, video);
                vos.add(vo);
            }
        }
        PageResultVo resultVo = new PageResultVo(page, pagesize, 0, vos);
        return resultVo;
    }
}
